﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.UI.WebControls;

namespace MCPro
{
    #region Enumeration

    /// <summary>
    /// List of all Date Format
    /// </summary>
    public enum DateOrientation
    {
        DayMonthYear,
        DayYearMonth,
        MonthDayYear,
        MonthYearDay,
        YearDayMonth,
        YearMonthDay,
        LongMonthDayYear
    }

    #endregion Enumeration

    #region Classes

    /// <summary>
    /// ProcessCode Main class that handles extra query and data processing procedures
    /// </summary>
    public class ProcessCode
    {
        /// <summary>
        /// Convert the Amount (number) to Amount words(string)
        /// </summary>
        /// <param name="value">String Amount (Number) to be converted</param>
        /// <returns></returns>
        public string AmountToWords(string value)
        {
            long c, liDigit;
            string lsDescs = "";
            string lsDescsTotal = "";
            long[] num = new long[5];
            long adcAmount;

            try
            {
                decimal _value = decimal.Parse(value);

                string[] ones_descs = { "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine" };
                string[] number_descs = { "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen" };
                string[] ten_descs = { "Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety" };
                string[] thousand_descs = { "Billion", "Million", "Thousand", "Pesos", "Centavo(s)" };

                adcAmount = (long)(_value);

                num[0] = adcAmount / 1000000000;
                num[1] = (adcAmount % 1000000000) / 1000000;
                num[2] = (adcAmount % 1000000) / 1000;
                num[3] = adcAmount % 1000;
                num[4] = Convert.ToInt64(_value * 100 % 100);

                for (c = 0; c <= 4; c++)
                {
                    if (num[c] <= 0) continue;

                    //First Digit
                    liDigit = num[c] / 100;

                    if (liDigit >= 1)
                    {
                        lsDescs = ones_descs[liDigit - 1] + " " + "Hundred" + " ";
                    }

                    // Second Digit
                    liDigit = (num[c] % 100) / 10;

                    if ((liDigit == 1) && ((num[c] % 10) != 0))
                        lsDescs = lsDescs + number_descs[(num[c] % 10) - 1] + " ";
                    else
                    {
                        if (liDigit != 0)
                        {
                            lsDescs = lsDescs + ten_descs[liDigit - 1] + " ";
                        }

                        // Third Digit
                        liDigit = num[c] % 10;

                        if (liDigit >= 1)
                        {
                            lsDescs = lsDescs + ones_descs[liDigit - 1] + " ";
                        }
                    }

                    lsDescsTotal = lsDescsTotal + lsDescs + thousand_descs[c] + " ";
                    if (c == 3 && num[4] > 0) lsDescsTotal = lsDescsTotal + "And";
                    lsDescs = " ";
                }

                if (adcAmount > 0)
                    lsDescsTotal = lsDescsTotal + "Only";
            }
            catch (Exception ex)
            {
                lsDescsTotal = "None";
            }

            return lsDescsTotal;
        }

        /// <summary>
        /// Format Date  into a different Orientation
        /// </summary>
        /// <param name="value">Valid string Date, in any format</param>
        /// <param name="formatTo">enum Date Format</param>
        /// <param name="separator">Separator for the Date</param>
        /// <returns></returns>
        public string FormatDate(string value, DateOrientation formatTo, char separator)
        {
            try
            {
                DateTime _value = DateTime.Parse(value);
                string[] constDate = _value.ToShortDateString().Split('/');
                string finalFormat = "";
                switch (formatTo)
                {
                    case DateOrientation.DayMonthYear:
                        finalFormat = ((constDate[1].Count() == 1 ? "0" + constDate[1] : constDate[1]).Count() == 1 ? "0" + (constDate[1].Count() == 1 ? "0" + constDate[1] : constDate[1]) : (constDate[1].Count() == 1 ? "0" + constDate[1] : constDate[1])) + separator + (constDate[0].Count() == 1 ? "0" + constDate[0] : constDate[0]) + separator + constDate[2];
                        break;
                    case DateOrientation.DayYearMonth:
                        finalFormat = (constDate[1].Count() == 1 ? "0" + constDate[1] : constDate[1]) + separator + constDate[2] + separator + (constDate[0].Count() == 1 ? "0" + constDate[0] : constDate[0]);
                        break;
                    case DateOrientation.MonthDayYear:
                        finalFormat = (constDate[0].Count() == 1 ? "0" + constDate[0] : constDate[0]) + separator + (constDate[1].Count() == 1 ? "0" + constDate[1] : constDate[1]) + separator + constDate[2];
                        break;
                    case DateOrientation.MonthYearDay:
                        finalFormat = (constDate[0].Count() == 1 ? "0" + constDate[0] : constDate[0]) + separator + constDate[2] + separator + (constDate[1].Count() == 1 ? "0" + constDate[1] : constDate[1]);
                        break;
                    case DateOrientation.YearDayMonth:
                        finalFormat = constDate[2] + separator + (constDate[1].Count() == 1 ? "0" + constDate[1] : constDate[1]) + separator + (constDate[0].Count() == 1 ? "0" + constDate[0] : constDate[0]);
                        break;
                    case DateOrientation.YearMonthDay:
                        finalFormat = constDate[2] + separator + (constDate[0].Count() == 1 ? "0" + constDate[0] : constDate[0]) + separator + (constDate[1].Count() == 1 ? "0" + constDate[1] : constDate[1]);
                        break;
                    case DateOrientation.LongMonthDayYear:
                        finalFormat = MonthName(Int32.Parse(constDate[0])) + " " + (constDate[1].Count() == 1 ? "0" + constDate[1] : constDate[1]) + ", " + constDate[2];
                        break;
                }
                return finalFormat;
            }
            catch (Exception)
            {
                return "error";
            }
        }

        /// <summary>
        ///Support Function for Formatdate, to get Month Description
        /// </summary>
        /// <param name="mMonth">Int value of a Month</param>
        /// <returns></returns>
        private string MonthName(int mMonth)
        {
            string mStrMonth = "";

            switch (mMonth)
            {
                case 1:
                    mStrMonth = "January";
                    break;
                case 2:
                    mStrMonth = "February";
                    break;
                case 3:
                    mStrMonth = "March";
                    break;
                case 4:
                    mStrMonth = "April";
                    break;
                case 5:
                    mStrMonth = "May";
                    break;
                case 6:
                    mStrMonth = "June";
                    break;
                case 7:
                    mStrMonth = "July";
                    break;
                case 8:
                    mStrMonth = "August";
                    break;
                case 9:
                    mStrMonth = "September";
                    break;
                case 10:
                    mStrMonth = "October";
                    break;
                case 11:
                    mStrMonth = "November";
                    break;
                case 12:
                    mStrMonth = "December";
                    break;
            }

            return mStrMonth;
        }

        /// <summary>
        /// Get Client IPAddress
        /// </summary>
        /// <returns></returns>
        public string IpAddress()
        {
            string strIpAddress;
            //System.Net.IPHostEntry strIpAddress = new System.Net.IPHostEntry();
            strIpAddress = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
            if (strIpAddress == null)
                strIpAddress = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
            //strIpAddress = System.Net.Dns.GetHostEntry(Request.ServerVariables["REMOTE_HOST"]);
            return strIpAddress;
        }

        /// <summary>
        /// Make a simple addition of very very large numbers ex. 9e1000++
        /// </summary>
        /// <param name="num1">First non Negative Number</param>
        /// <param name="num2">Second non Negative Number</param>
        /// <returns></returns>
        public string AddLargeNumbers(string num1, string num2)
        {
            List<int> cn1 = num1.ToCharArray().ToList().ConvertAll(x => Convert.ToInt32(x));
            List<int> cn2 = num2.ToCharArray().ToList().ConvertAll(x => Convert.ToInt32(x));
            cn1.Reverse();
            cn2.Reverse();

            int maxCount = 0;
            if (cn1.Count > cn2.Count)
            {
                maxCount = cn1.Count + 1;
            }
            else
            {
                maxCount = cn2.Count + 1;
            }

            for (int i = 0; i < cn1.Count; i++)
            {
                cn1[i] = cn1[i] - Convert.ToInt32('0');
            }

            for (int i = 0; i < cn2.Count; i++)
            {
                cn2[i] = cn2[i] - Convert.ToInt32('0');
            }

            while (cn1.Count < maxCount)
            {
                cn1.Add(0);
            }

            while (cn2.Count < maxCount)
            {
                cn2.Add(0);
            }

            List<int> result = new List<int>();
            int carryover = 0;
            for (int i = 0; i < maxCount; i++)
            {
                int c = cn1[i] + cn2[i] + carryover;
                if (c >= 10)
                {
                    c -= 10;
                    carryover = 1;
                }
                else
                {
                    carryover = 0;
                }
                result.Add(c);
            }

            result.Reverse();
            System.Text.StringBuilder charResult = new System.Text.StringBuilder();
            for (int i = (result[0] == 0 ? 1 : 0); i < maxCount; i++)
            {
                charResult.Append(result[i].ToString());
            }
            return charResult.ToString();
        }
    }

    #endregion Classes
}